using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Media;
using Kent.Boogaart.HelperTrinity;

namespace Intuipic.Data
{
	/// <summary>
	/// A base class for all informational classes.
	/// </summary>
	public abstract class InformationBase : INotifyPropertyChanged
	{
		private readonly string _name;
		private readonly string _path;
		private readonly ImageSource _closedIcon;
		private readonly ImageSource _openIcon;
		private readonly InformationBase _parent;
		private ICollection<InformationBase> _children;

		/// <summary>
		/// Gets the name of the informational item, which is used when displaying the item.
		/// </summary>
		public string Name
		{
			get
			{
				return _name;
			}
		}

		/// <summary>
		/// Gets the path this information item represents.
		/// </summary>
		public string Path
		{
			get
			{
				return _path;
			}
		}

		/// <summary>
		/// Gets the icon used when the informational item is closed.
		/// </summary>
		public ImageSource ClosedIcon
		{
			get
			{
				return _closedIcon;
			}
		}

		/// <summary>
		/// Gets the icon used when the informational item is open.
		/// </summary>
		public ImageSource OpenIcon
		{
			get
			{
				return _openIcon;
			}
		}

		/// <summary>
		/// Gets the parent of this information item.
		/// </summary>
		protected InformationBase Parent
		{
			get
			{
				return _parent;
			}
		}

		/// <summary>
		/// Gets the children of this information item.
		/// </summary>
		public ICollection<InformationBase> Children
		{
			get
			{
				if (!AreChildrenLoaded)
				{
					//lazy-load children
					LoadChildren();
				}

				return _children;
			}
		}

		/// <summary>
		/// Gets a value indicating whether children are loaded.
		/// </summary>
		protected bool AreChildrenLoaded
		{
			get
			{
				return (_children != null);
			}
		}

		/// <summary>
		/// Occurs whenever a property on this object changes in value.
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;

		/// <summary>
		/// Constructs an instance of <c>InformationBase</c> with the details provided.
		/// </summary>
		protected InformationBase(string name, string path, ImageSource closedIcon, ImageSource openIcon, InformationBase parent)
		{
			Debug.Assert(name != null);

			_name = name;
			_path = path;
			_closedIcon = closedIcon;
			_openIcon = openIcon;
			_parent = parent;
		}

		/// <summary>
		/// Converts this <c>InformationBase</c> to an instance of <c>string</c>.
		/// </summary>
		public override string ToString()
		{
			return string.Format("{0} [{1}]", Name, _path);
		}

		/// <summary>
		/// Raises the <see cref="PropertyChanged"/> event.
		/// </summary>
		/// <param name="propertyName">
		/// The name of the property that changed.
		/// </param>
		protected void OnPropertyChanged(string propertyName)
		{
			Debug.Assert(propertyName != null);
			EventHelper.Raise(PropertyChanged, this, new PropertyChangedEventArgs(propertyName));
		}

		private void LoadChildren()
		{
			Debug.Assert(_children == null);
			_children = new List<InformationBase>();
			LoadChildrenCore();

			OnPropertyChanged("Children");
		}

		/// <summary>
		/// Called when child items should be loaded.
		/// </summary>
		protected abstract void LoadChildrenCore();

		/// <summary>
		/// Adds the path for this informational item to the source directories in the current settings.
		/// </summary>
		protected internal virtual void AddPath()
		{
			Settings.Current.SourceDirectories.Add(_path);
		}

		/// <summary>
		/// Removes the path of this informational item from the source directories in the current settings.
		/// </summary>
		protected internal virtual void RemovePath()
		{
			Settings.Current.SourceDirectories.Remove(_path.ToLower());
		}
	}
}
